using Engine;
using Game;
using GameEntitySystem;

namespace SCIENEW {
    public class FluidTankDeviceBehavior : EntityDeviceBehavior<ComponentFluidTank> {
        public SubsystemTerrain m_subsystemTerrain;
        public FluidTankDeviceBehavior(Project project) : base(project) {
            m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
        }

        public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ) {
            int blockValue = m_subsystemTerrain.Terrain.GetCellValueFast(x, y - 1, z);
            if (BlocksManager.Blocks[Terrain.ExtractContents(blockValue)].IsTransparent_(blockValue)
                && !(BlocksManager.Blocks[Terrain.ExtractContents(blockValue)] is BaseDeviceBlock
                && DevicesBlockManager.GetDevice(blockValue) is FluidTankDevice))
                m_subsystemTerrain.DestroyCell(0, x, y, z, 0, false, false);
        }

        public override void OnBlockAdded(int value, int oldValue, int x, int y, int z) {
            int blockID = m_subsystemTerrain.Terrain.GetCellValueFast(x, y - 1, z);
            int blockIndex = Terrain.ExtractContents(blockID);
            if (BlocksManager.Blocks[blockIndex] is BaseDeviceBlock
                && DevicesBlockManager.GetDevice(blockID) is FluidTankDevice) {

                //更新实体组件
                Point3 point = new(x, y, z);
                ComponentBlockEntity componentBlockEntity;
                while (!DeviceEntityUtils.GetDeviceEntity(Project.FindSubsystem<SubsystemTerrain>(true), point, out componentBlockEntity) || componentBlockEntity.Entity.FindComponent<ComponentFluidTank>() == null) {
                    point -= Point3.UnitY;
                }
                componentBlockEntity?.Entity.FindComponent<ComponentFluidTank>(true).UpdateVolume();

                return;
            }

            base.OnBlockAdded(value, oldValue, x, y, z);
        }

        public override void OnBlockRemoved(int value, int newValue, int x, int y, int z) {
            int blockID = m_subsystemTerrain.Terrain.GetCellValueFast(x, y - 1, z);
            int blockIndex = Terrain.ExtractContents(blockID);
            if (BlocksManager.Blocks[blockIndex] is BaseDeviceBlock
                && DevicesBlockManager.GetDevice(blockID) is FluidTankDevice) {

                //更新实体组件
                Point3 point = new(x, y, z);
                ComponentBlockEntity componentBlockEntity;
                while (!DeviceEntityUtils.GetDeviceEntity(Project.FindSubsystem<SubsystemTerrain>(true), point, out componentBlockEntity) || componentBlockEntity.Entity.FindComponent<ComponentFluidTank>() == null) {
                    point -= Point3.UnitY;
                }
                componentBlockEntity?.Entity.FindComponent<ComponentFluidTank>(true).UpdateVolume();

                return;
            }

            base.OnBlockRemoved(value, newValue, x, y, z);
        }

        public override void OnBlockModified(int value, int oldValue, int x, int y, int z) {
            int blockID = m_subsystemTerrain.Terrain.GetCellValueFast(x, y - 1, z);
            int blockIndex = Terrain.ExtractContents(blockID);
            if (BlocksManager.Blocks[blockIndex] is BaseDeviceBlock
                && DevicesBlockManager.GetDevice(blockID) is FluidTankDevice) {

                //更新实体组件
                Point3 point = new(x, y, z);
                ComponentBlockEntity componentBlockEntity;
                while (!DeviceEntityUtils.GetDeviceEntity(Project.FindSubsystem<SubsystemTerrain>(true), point, out componentBlockEntity) || componentBlockEntity.Entity.FindComponent<ComponentFluidTank>() == null) {
                    point -= Point3.UnitY;
                }
                componentBlockEntity?.Entity.FindComponent<ComponentFluidTank>(true).UpdateVolume();

                return;
            }
            base.OnBlockModified(value, oldValue, x, y, z);
        }

        public override bool OnInteract(TerrainRaycastResult raycastResult, ComponentMiner componentMiner) {
            int blockIndex = Terrain.ExtractContents(componentMiner.ActiveBlockValue);
            if (BlocksManager.Blocks[blockIndex] is BaseDeviceBlock
                && DevicesBlockManager.GetDevice(componentMiner.ActiveBlockValue) is FluidTankDevice) {
                return false;
            }

            while (!DeviceEntityUtils.GetDeviceEntity(Project.FindSubsystem<SubsystemTerrain>(true), raycastResult.CellFace.Point, out _)) {
                raycastResult.CellFace.Point -= Point3.UnitY;
            }
            return base.OnInteract(raycastResult, componentMiner);
        }
    }
}